from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QMessageBox, QSizePolicy
from PyQt5 import QtWidgets,QtGui
import sys
import os
import cv2
import copy
import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)
from loguru import logger
from PyQt5 import QtCore
from PyQt5.QtGui import QIcon, QImage, QPixmap
from windows.login import Ui_Form as login_win
from windows.mainwin import Ui_MainWindow as main_win
from windows.waringdialog import Ui_Form as warndailog
from windows.camerachoose import Ui_Form as camerachoose
from PyQt5 import QtSql
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import numpy as np
import os
from PyQt5.QtSql import QSqlQuery
from folder_ProgressBar import Progress_show
# import objtracker
from objdetector import Detector
import pygame
import random


# 获取当前工作的路径
WORKPATH = os.getcwd()

# 警告窗口
class Warning(QWidget,warndailog):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        # 设置窗口标题
        self.setWindowTitle("侵入警告")
        # 设置窗口图标
        self.setWindowIcon(QIcon('res/falllogo.png'))
        # 设置窗口固定大小
        self.setFixedSize(350, 140)
        self.pushButton.clicked.connect(self.close)

# 摄像头选择窗口
class camerapathchoose(QWidget,camerachoose):
    sendcamerapath = pyqtSignal(str)
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.camerapath = ""
        # 设置窗口标题
        self.setWindowTitle("选择摄像头地址")
        # 设置窗口图标
        self.setWindowIcon(QIcon('res/falllogo.png'))
        # 设置窗口固定大小
        self.setFixedSize(350, 100)
        self.btn_upload.clicked.connect(self.sendpath)

    def sendpath(self):
        self.camerapath = self.lineEdit_camerapath.text()
        self.sendcamerapath.emit(str(self.camerapath))

# 登录窗口
class Login(QWidget,login_win):
    loginsuccess = pyqtSignal()  # 登录成功的信号
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.initui()
        self.database_init()
        self.init_slot()

    # 设置窗口的基本信息
    def initui(self):
        # 设置窗口标题
        self.setWindowTitle("基于树莓派4B的独居老人跌倒系统的设计与实现")
        # 设置窗口图标
        self.setWindowIcon(QIcon('res/falllogo.png'))
        # 设置窗口固定大小
        self.setFixedSize(430, 300)

    # 初始化槽函数
    def init_slot(self):
        self.btn_login.clicked.connect(self.login)
        self.btn_register.clicked.connect(self.register)

    # 数据库初始化
    def database_init(self):
        # 连接数据库
        self.database = QtSql.QSqlDatabase.addDatabase('QSQLITE')
        self.database.setDatabaseName('userinfo.db')
        if self.database.open():
            logger.info("数据库连接成功")
        # 新建表
        q = QSqlQuery()
        sql_code = 'CREATE TABLE users (username VARCHAR(255) PRIMARY KEY,password VARCHAR(255) NOT NULL);'
        if q.exec_(sql_code):
            print('create a table users')

    # 用户登录
    def login(self):
        input_username = self.lineEdit_username.text()
        input_passwd = self.lineEdit_passwd.text()
        q = QSqlQuery()
        # 查询数据库中是否存在该用户名
        sql_code = f'SELECT * FROM users WHERE username = \'{input_username}\';'
        q.exec_(sql_code)  # 执行sql语句
        if q.next():
            result = q.value(1)
            if result == input_passwd and result != '':  # 登录成功
                QMessageBox.information(self, '通知', '登录成功', QMessageBox.Ok, QMessageBox.Ok)
                self.loginsuccess.emit()
                self.close()
            elif result != input_passwd:
                QMessageBox.warning(self, '警告', '密码错误，请重新输入', QMessageBox.Ok, QMessageBox.Ok)
        else:
            QMessageBox.warning(self, '警告', '没有当前用户名，请先进行注册', QMessageBox.Ok, QMessageBox.Ok)

    # 用户注册
    def register(self):
        input_username = self.lineEdit_username.text()
        input_passwd = self.lineEdit_passwd.text()
        q = QSqlQuery()
        # 查询数据库中是否存在该用户名
        sql_code = f'SELECT * FROM users WHERE username = \'{input_username}\';'
        q.exec_(sql_code)  # 执行sql语句
        if q.next():
            QMessageBox.warning(self, '警告', '该用户名已经存在！', QMessageBox.Ok, QMessageBox.Ok)
        elif input_passwd == "":
            QMessageBox.warning(self, '警告', '密码不能为空！', QMessageBox.Ok, QMessageBox.Ok)
        elif input_username == "":
            QMessageBox.warning(self, '警告', '用户名不能为空！', QMessageBox.Ok, QMessageBox.Ok)
        else:
            sql_insert = f'INSERT INTO users (username, password) VALUES (\'{input_username}\', \'{input_passwd}\');'
            if q.exec_(sql_insert):  # 执行sql语句
                QMessageBox.information(self, '通知', '注册成功', QMessageBox.Ok, QMessageBox.Ok)

class DetThread(QThread):
    send_img = pyqtSignal(np.ndarray)
    send_progress = pyqtSignal(float)  # 发送视频检测时的进度
    send_count = pyqtSignal(int)       # 发送文件夹检测时，已检测的文件数量
    send_frame_count = pyqtSignal(int)
    send_result = pyqtSignal(list)
    end_singal = pyqtSignal()
    def __init__(self,model_path,labelWidgets, videoWriter,cur_frame,iou,Conf):
        super().__init__()
        self.filepath = ""
        self.camera_path = ""
        self.filetype = "file"
        self.cur_frame = cur_frame
        self.end_flag = False
        self.pause_flag = False
        self.iou_threshold = iou
        self.conf_threshold = Conf
        self.labelWidgets = labelWidgets
        self.videoWriter = videoWriter
        self.detecter = Detector()
        self.detecter.init_model(model_path)
        self.detgap = 1  # 检测频率（几帧检测一次，根据电脑性能设置）
        self.idlist = []

    @staticmethod
    def get_image_files(folder_path):
        if folder_path:
            image_files = []
            for file in os.listdir(folder_path):
                if file.lower().endswith(('.png', '.jpg', '.jpeg')):
                    image_files.append(file)
            return image_files
        else:
            pass

    @staticmethod
    def adjust_vertices_flat_list(vertices, original_size, displayed_size):
        if vertices:
            # 计算宽度和高度的缩放比例
            scale_x = original_size[0] / displayed_size[0]
            scale_y = original_size[1] / displayed_size[1]
            # 分组顶点并调整坐标
            adjusted_vertices = [(int(vertices[i] * scale_x), int(vertices[i + 1] * scale_y)) for i in
                                 range(0, len(vertices), 2)]
            return adjusted_vertices
        else:
            pass

    def run(self):
        if self.filetype == 'file':
            img = cv2.imdecode(np.fromfile(self.filepath, dtype=np.uint8), -1)            # 打开图片
            img_raw = copy.deepcopy(img)
            if self.labelWidgets.Polygon_list:
                height_ori, width_ori = img.shape[:2]                                     # 获取图片的原始高宽
                height_after,width_after = self.labelWidgets.originalPixmap.size().height(),self.labelWidgets.originalPixmap.size().width()  # 获取放置图片的QLabel的大小
                adjusted_polygon_list = self.adjust_vertices_flat_list(self.labelWidgets.Polygon_list,(width_ori,height_ori),(width_after,height_after))
                # 创建与图片大小相同的掩模，并填充为0（全黑）
                mask = np.zeros(img.shape[:2], dtype=np.uint8)
                # 根据多边形顶点创建多边形掩模，将多边形内的像素值设置为255
                points = np.array(adjusted_polygon_list, dtype=np.int32)
                pts = points.reshape((-1, 1, 2))
                cv2.fillPoly(mask, [points], 255)
                # 将掩模应用到图片上，只保留多边形内的部分，其余变为黑色
                img_mask = cv2.bitwise_and(img, img, mask=mask)
                det_result = self.detecter.detect(img_mask, self.conf_threshold, self.iou_threshold)
                img = self.detecter.drawboxs(img_raw,det_result)
                cv2.polylines(img, [pts], isClosed=True, color=(255, 0, 0), thickness=3)
            else:
                det_result = self.detecter.detect(img, self.conf_threshold, self.iou_threshold)
                img = self.detecter.drawboxs(img_raw,det_result)

            # 构建文件保存路径
            cv2.imwrite(f'./out/detect_{self.filepath.split("/")[-1]}',img)
            self.send_img.emit(img)
            self.end_singal.emit()

        elif self.filetype == 'folder':
            # 获得这个文件夹中所有的图片
            image_files = self.get_image_files(self.filepath)
            for index,image in enumerate(image_files):
                if self.end_flag:
                    break
                image_path = os.path.join(self.filepath,image)
                img = cv2.imdecode(np.fromfile(image_path, dtype=np.uint8), -1)
                det_result = self.detecter.detect(img, self.conf_threshold, self.iou_threshold)
                img = self.detecter.drawboxs(img,det_result)
                # 构建保存文件路径
                if not os.path.exists('out/detect_res'):
                    os.makedirs('out/detect_res')
                save_filepath =  os.path.join('out/detect_res',image)
                cv2.imwrite(save_filepath,img)
                self.send_img.emit(img)
                self.send_count.emit(index+1)      # 发送当前已经处理的图片数量
            if not self.end_flag:
                self.end_singal.emit()

        elif self.filetype == 'video':
            cap = cv2.VideoCapture(self.filepath)
            cap.set(cv2.CAP_PROP_POS_FRAMES, self.cur_frame)
            self.frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) # 获取视频总帧数
            self.send_frame_count.emit(self.frame_count)
            while not self.end_flag:
                rval, frame = cap.read()
                frame_raw = copy.deepcopy(frame)
                if self.end_flag:
                    self.cur_frame = 1
                    break
                if self.pause_flag:
                    break
                # frame_raw = copy.deepcopy(frame)
                if not rval:
                    break
                if self.labelWidgets.Polygon_list:
                    height_ori, width_ori = frame.shape[:2]  # 图片的原始高宽
                    height_after, width_after = self.labelWidgets.originalPixmap.size().height(), self.labelWidgets.originalPixmap.size().width()
                    adjusted_polygon_list = self.adjust_vertices_flat_list(self.labelWidgets.Polygon_list,
                                                                           (width_ori, height_ori),
                                                                           (width_after, height_after))
                    # 创建与图片大小相同的掩模，并填充为0（全黑）
                    mask = np.zeros(frame.shape[:2], dtype=np.uint8)
                    # 根据多边形顶点创建多边形掩模，将多边形内的像素值设置为255
                    points = np.array(adjusted_polygon_list, dtype=np.int32)
                    pts = points.reshape((-1, 1, 2))
                    cv2.fillPoly(mask, [points], 255)
                    # 将掩模应用到图片上，只保留多边形内的部分，其余变为黑色
                    img_mask = cv2.bitwise_and(frame, frame, mask=mask)
                    if self.cur_frame % self.detgap == 0:
                        # det_result = detect(model=self.model, img=img_mask,conf_thres=self.conf_threshold,iou_thres=self.iou_threshold)
                        det_result = self.detecter.detect(img_mask, self.conf_threshold, self.iou_threshold)
                        self.send_result.emit(det_result)
                        # img = self.draw_box(frame_raw, det_result)
                        img = self.detecter.drawboxs(frame_raw, det_result)
                    else:
                        img = frame_raw
                    cv2.polylines(img, [pts], isClosed=True, color=(255, 0, 0), thickness=3)

                else:
                    if self.cur_frame % self.detgap == 0:
                        det_result = self.detecter.detect(frame, self.conf_threshold, self.iou_threshold)
                        self.send_result.emit(det_result)
                        # img = self.draw_box(frame_raw, det_result)
                        img = self.detecter.drawboxs(frame_raw, det_result)
                    else:
                        img = frame_raw

                # 发送信号以更新进度条
                self.videoWriter.write(img)
                self.send_img.emit(img)
                self.send_progress.emit(self.cur_frame)
                self.cur_frame += 1
            if not self.pause_flag and not self.end_flag:
                self.end_singal.emit()
                cap.release()

        elif self.filetype == 'camera':
            cap = cv2.VideoCapture(self.filepath)
            while not self.end_flag:
                rval, frame = cap.read()
                frame_raw = copy.deepcopy(frame)
                if not rval:
                    break
                if self.labelWidgets.Polygon_list:
                    height_ori, width_ori = frame.shape[:2]  # 图片的原始高宽
                    height_after, width_after = self.labelWidgets.originalPixmap.size().height(), self.labelWidgets.originalPixmap.size().width()
                    adjusted_polygon_list = self.adjust_vertices_flat_list(self.labelWidgets.Polygon_list,
                                                                           (width_ori, height_ori),
                                                                           (width_after, height_after))
                    # 创建与图片大小相同的掩模，并填充为0（全黑）
                    mask = np.zeros(frame.shape[:2], dtype=np.uint8)
                    # 根据多边形顶点创建多边形掩模，将多边形内的像素值设置为255
                    points = np.array(adjusted_polygon_list, dtype=np.int32)
                    pts = points.reshape((-1, 1, 2))
                    cv2.fillPoly(mask, [points], 255)
                    # 将掩模应用到图片上，只保留多边形内的部分，其余变为黑色
                    img_mask = cv2.bitwise_and(frame, frame, mask=mask)
                    if self.cur_frame % self.detgap == 0:
                        # det_result = detect(model=self.model, img=img_mask,conf_thres=self.conf_threshold,iou_thres=self.iou_threshold)
                        det_result = self.detecter.detect(img_mask, self.conf_threshold, self.iou_threshold)
                        self.send_result.emit(det_result)
                        # img = self.draw_box(frame_raw, det_result)
                        img = self.detecter.drawboxs(frame_raw, det_result)
                    else:
                        img = frame_raw
                    cv2.polylines(img, [pts], isClosed=True, color=(255, 0, 0), thickness=3)
                else:
                    if self.cur_frame % self.detgap == 0:
                        det_result = self.detecter.detect(frame, self.conf_threshold, self.iou_threshold)
                        self.send_result.emit(det_result)
                        # img = self.draw_box(frame_raw, det_result)
                        img = self.detecter.drawboxs(frame_raw, det_result)
                    else:
                        img = frame_raw

                self.videoWriter.write(img)
                self.send_img.emit(img)
            cap.release()
            if not self.pause_flag and not self.end_flag:
                self.end_singal.emit()

class mainwin(QMainWindow,main_win):
    send_pause_singal = pyqtSignal()
    send_end_singal = pyqtSignal()
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.initUI()
        self.init_slot()
        self.initvoice()
    def initUI(self):
        # 设置窗口标题
        self.setWindowTitle("人员侵入智能检测系统")
        # 设置窗口图标
        self.setWindowIcon(QIcon('res/falllogo.png'))
        self.statusBar = QStatusBar()
        self.setStatusBar(self.statusBar)
        self.setWindowFlag(Qt.FramelessWindowHint) #设置窗口标志：隐藏窗口边框
        # 设置状态栏字体颜色为红色
        self.statusBar.setStyleSheet("color: black")
        # 创建一个标签，并将其作为永久性小部件添加到状态栏的右侧
        self.rightStatusLabel = QLabel('By：SUPINe')
        self.statusBar.addPermanentWidget(self.rightStatusLabel)
        # 用来控制检测进程是否在工作的变量
        self.workpause = True  # 用来控制视频的暂停和播放 True表示当前暂停，False表示当前播放
        self.workend = True  # 用来控制视频的暂停和播放   True表示当前停止，False表示当前播放
        self.cur_frame = 1
        self.tableWidget_detres.verticalHeader().hide()
        self.tableWidget_detres.setEditTriggers(QTableWidget.NoEditTriggers)
        # self.tableWidget_detres.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
        self.tableWidget_detres.setColumnCount(4)
        self.tableWidget_detres.setShowGrid(False)
        self.det_thead_cur_frame = 1
        # 模型权重文件夹路径
        self.model_weight = "model_weight"
        self.videoWriter = ''
        # 保存文件类型
        self.file_type = 'file'
        self.file_path = ""
        self.raw_image = ""
        self.detect_image = ""
        self.detect_show_label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        # 获取权重文件
        scene = os.listdir(self.model_weight)
        self.comboBox_weight.addItems(scene)
        self.SpinBox_conf.setSingleStep(0.01)
        self.SpinBox_iou.setSingleStep(0.01)
        # 绑定QSpinBox和QSlider
        self.SpinBox_conf.valueChanged.connect(lambda x: self.change_val(x, 'confSpinBox'))
        self.Slider_conf.valueChanged.connect(lambda x: self.change_val(x, 'confSlider'))
        self.SpinBox_iou.valueChanged.connect(lambda x: self.change_val(x, 'iouSpinBox'))
        self.Slider_iou.valueChanged.connect(lambda x: self.change_val(x, 'iouSlider'))
        # 初始化QSpinBox和QSlider的值
        self.SpinBox_conf.setValue(0.50)
        self.SpinBox_iou.setValue(0.50)
        # 设置进度条
        self.progressBar.reset() # 进度条清零
        # 设置btn_polygon能够选中和不选中
        self.btn_polygon.setCheckable(True)
        self.btn_voice.setCheckable(True)
        self.btn_dialog.setCheckable(True)
        # 设置报警
        self.warningwin = Warning()
        self.lastStateWasFall = False  # 初始化状态变量
        # 设置摄像头选择
        self.camerawin  = camerapathchoose()
        self.camerawin.sendcamerapath.connect(self.camera_choose)
        # 设置播报语音路径
        self.voice_path = "res/warning.mp3"
        # 已经得到的ID
        ID_list= []

        # 设置背景
        # 加载并缩放背景图像
        backgroundpixmap = QPixmap(":/img/res/background.png")
        scaled_pixmap = backgroundpixmap.scaled(self.size(), Qt.KeepAspectRatioByExpanding)
        # 设置缩放后的图像为背景
        palette = QPalette()
        palette.setBrush(QPalette.Window, QBrush(scaled_pixmap))
        self.setPalette(palette)
        # 窗口最大化
        self.maximized = False  # 初始状态，窗口没有被最大化
        self.last_x, self.last_y = 0, 0  # 最后一次记忆的窗口位置
        self.nol_width, self.nol_height = self.size().width(), self.size().height()  # 正常大小
        self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
        # 设置splitter的比例
        self.splitter_2.setSizes([100, 700])
        self.cur_img = None
        self.m_flag = True
        self.m_Position = QPoint(0,0)

    def getimage(self, x):
        self.cur_img = x
        self.show_image(self.detect_show_label)


    def init_slot(self):
        self.btn_file.clicked.connect(self.file_choose)
        self.btn_floder.clicked.connect(self.floder_choose)
        self.btn_video.clicked.connect(self.video_choose)
        self.btn_camera.clicked.connect(self.choosecamerashow)
        self.btn_outputfloder.clicked.connect(self.result_output)
        self.btn_run.clicked.connect(self.work)
        self.btn_run_2.clicked.connect(self.end)
        self.btn_polygon.clicked.connect(self.printstatus)
        self.btn_voice.clicked.connect(self.voicestatus)
        self.btn_dialog.clicked.connect(self.dialogstatus)
        self.maxButton.clicked.connect(self.on_max_btn_clicked)
        self.minButton.clicked.connect(self.minimizeAction)
        self.closeButton.clicked.connect(lambda: self.close())

    def initvoice(self):
        pygame.mixer.init()
        pygame.mixer.music.load(self.voice_path)
    def work(self):
        # 播放-暂停
        if self.workpause == False: # 当前正在播放，要暂停
            # 更换图标
            self.btn_run.setStyleSheet("QPushButton{qproperty-icon: url(:/icon/res/彩色图标/暂停.png)}")
            self.workpause = True
            self.send_pause_singal.emit()
            self.statusBar.showMessage("检测暂停")
        # 当前正在停止，要播放
        else:
            # 判断是否选择文件路径
            if self.file_path == "" and self.file_type != 'camera':
                QMessageBox.critical(self,'错误','未选择待检测文件路径',QMessageBox.Yes)
                return
            if self.file_type == 'folder':
                self.folder_progress.show()
            # 更换图标
            self.statusBar.showMessage("检测开始")
            self.btn_run.setStyleSheet("QPushButton{qproperty-icon: url(:/icon/res/彩色图标/播放.png)}")
            logger.info("当前检测模式：{}",self.file_type)
            logger.info("当前检测文件路径：{}", self.file_path)
            logger.info("当前检测模型为：{}", self.comboBox_weight.currentText())
            self.model_path = os.path.join(self.model_weight,self.comboBox_weight.currentText())
            # 获取参数
            iou_threshold = float(self.SpinBox_iou.text())
            Conf_threshold = float(self.SpinBox_conf.text())
            # 获取选择的区域信息
            self.areainfo = self.detect_show_label.Polygon_list     # 记录当前选择的区域信息
            # 判断当前是停止状态还是暂停状态
            if self.workend:  # 如果workend为true，表示当前是停止状态
                self.det_thead = DetThread(model_path=self.model_path,labelWidgets=self.detect_show_label,videoWriter=self.videoWriter,cur_frame=1,iou=iou_threshold,Conf=Conf_threshold)
                self.workend = False
                self.workpause = False
            elif self.workpause == True:  # 如果workend为False并且workpause为True，代表当前是暂停状态
                self.det_thead = DetThread(model_path=self.model_path,labelWidgets=self.detect_show_label,videoWriter=self.videoWriter,cur_frame=self.cur_frame,iou=iou_threshold,Conf=Conf_threshold)
                self.workpause = False
            self.det_thead.send_img.connect(lambda x: self.getimage(x))
            self.det_thead.send_progress.connect(lambda x: self.updateprogress(x))
            self.det_thead.send_frame_count.connect(lambda frame_count:self.progressBar.setMaximum(frame_count))
            self.det_thead.end_singal.connect(self.end)
            self.det_thead.send_result.connect(self.disposereslut)
            self.det_thead.send_count.connect(self.folder_updatecount)
            self.send_pause_singal.connect(self.pause)
            self.send_end_singal.connect(self.end)
            self.det_thead.filepath = self.file_path
            self.det_thead.filetype = self.file_type
            self.det_thead.start()

    def printstatus(self):
        if self.btn_polygon.isChecked():
            self.btn_polygon.setStyleSheet("background-color: rgba(48,148,243,80);")
            self.detect_show_label.enableDrawing(True)
        else:
            self.detect_show_label.enableDrawing(False)
            self.btn_polygon.setStyleSheet("QPushButton{background-color: rgba(200, 200, 200,0);}QPushButton::hover {border-style: solid;border-width: 0px;border-radius: 0px;background-color: rgba(48,148,243,80);}")

    def voicestatus(self):
        if self.btn_voice.isChecked():
            self.btn_voice.setStyleSheet("background-color: rgba(48,148,243,80);")
        else:
            self.btn_voice.setStyleSheet(
                "QPushButton{background-color: rgba(200, 200, 200,0);}QPushButton::hover {border-style: solid;border-width: 0px;border-radius: 0px;background-color: rgba(48,148,243,80);}")

    def heatmapshow(self):
        if self.btn_heatmap.isChecked():
            self.btn_heatmap.setStyleSheet("background-color: rgba(48,148,243,80);")
        else:
            self.btn_heatmap.setStyleSheet(
                "QPushButton{background-color: rgba(200, 200, 200,0);}QPushButton::hover {border-style: solid;border-width: 0px;border-radius: 0px;background-color: rgba(48,148,243,80);}")


    def dialogstatus(self):
        if self.btn_dialog.isChecked():
            self.btn_dialog.setStyleSheet("background-color: rgba(48,148,243,80);")
        else:
            self.btn_dialog.setStyleSheet(
                "QPushButton{background-color: rgba(200, 200, 200,0);}QPushButton::hover {border-style: solid;border-width: 0px;border-radius: 0px;background-color: rgba(48,148,243,80);}")

    def choosecamerashow(self):
        self.camerawin.show()

    def disposereslut(self, resultlist):
        # [82, 148, 103, 179, 'person', 9, 0]
        falldown = any(res[4] == "down" for res in resultlist)
        if falldown:
            self.showStatus.setText("当前有人跌倒")
            self.showStatus.setStyleSheet("border-radius:9px;border-color: rgb(170, 0, 0);background-color: rgba(200, 151, 53, 120);font: 800 16pt \"微软雅黑\";color: rgb(130, 0, 0);")
        else:
            self.showStatus.setText("正常")
            self.showStatus.setStyleSheet("border-radius:9px;border-color: rgb(170, 0, 0);background-color: rgba(200, 151, 53, 120);font: 800 16pt \"微软雅黑\";color: rgb(0, 130, 0);")
        if falldown and self.btn_voice.isChecked() and not pygame.mixer.music.get_busy():
            pygame.mixer.music.play()
        if falldown and self.btn_dialog.isChecked() and self.lastStateWasFall:
            self.warningwin.show()
        self.lastStateWasFall = falldown  # 更新状态变量
        self.tableWidget_detres.setRowCount(len(resultlist))  # 动态设置表格的行数
        for index, res in enumerate(resultlist):
            item1 = QTableWidgetItem(str(index + 1))
            item1.setTextAlignment(Qt.AlignCenter)
            self.tableWidget_detres.setItem(index, 0, item1)
            item2 = QTableWidgetItem(str(res[4]))
            item2.setTextAlignment(Qt.AlignCenter)
            self.tableWidget_detres.setItem(index, 1, item2)
            item3 = QTableWidgetItem(str(res[-1]))
            item3.setTextAlignment(Qt.AlignCenter)
            self.tableWidget_detres.setItem(index, 2, item3)
            item4 = QTableWidgetItem(str((res[0:4])))
            item4.setTextAlignment(Qt.AlignCenter)
            self.tableWidget_detres.setItem(index, 3, item4)
        # # 设置每列的宽度比例
        total_width = self.tableWidget_detres.width()
        column_widths = [0.1, 0.2, 0.3, 0.4]  # 列宽度比例
        for i in range(self.tableWidget_detres.columnCount()):
            self.tableWidget_detres.setColumnWidth(i, total_width * column_widths[i])


    def pause(self):
        self.det_thead.pause_flag = True

    def end(self):
        self.statusBar.showMessage("检测结束")
        self.btn_run.setStyleSheet("QPushButton{qproperty-icon: url(:/icon/res/彩色图标/暂停.png)}")
        self.workend = True
        self.workpause = True
        self.det_thead.end_flag = True
        QMessageBox.information(self, '消息', '当前检测完成',QMessageBox.Ok,QMessageBox.Ok)
        if self.file_type == 'folder':
            self.folder_progress.close()
        if self.file_type == 'video' or self.file_type == 'camera':
            self.videoWriter.release()

    def show_image(self, label):
        try:
            ih, iw, _ = self.cur_img.shape
            w = label.geometry().width()
            h = label.geometry().height()
            # keep original aspect ratio
            if iw / w > ih / h:
                scal = w / iw
                nw = w
                nh = int(scal * ih)
                img_src_ = cv2.resize(self.cur_img, (nw, nh),interpolation=cv2.INTER_AREA)
            else:
                scal = h / ih
                nw = int(scal * iw)
                nh = h
                img_src_ = cv2.resize(self.cur_img, (nw, nh),interpolation=cv2.INTER_AREA)
            # calculate center position
            x = (w - nw) // 2
            y = (h - nh) // 2
            # 设置label的背景色为黑色
            label.setStyleSheet("QLabel {background-color: black;}")
            label.setAlignment(QtCore.Qt.AlignCenter)  # 使图片在label中居中
            frame = cv2.cvtColor(img_src_, cv2.COLOR_BGR2RGB)
            img = QImage(frame.data, frame.shape[1], frame.shape[0], frame.shape[2] * frame.shape[1],
                         QImage.Format_RGB888)
            pixmap = QtGui.QPixmap.fromImage(img)
            label.setOriginalPixmap(pixmap)

        except Exception as e:
            print(repr(e))

    def updateprogress(self,x):
        # logger.info(f"当前进度：{x}")
        self.progressBar.setValue(x)
        self.cur_frame = x

    def folder_updatecount(self,x):
        all_num = len(DetThread.get_image_files(self.file_path))
        self.statusBar.showMessage(f"当前已经进行: {x}/{all_num}")
        # 更新进度条的值
        self.folder_progress.pgb.setValue(x)
        self.folder_progress.pgb.setFormat(f'已经检测 {self.folder_progress.pgb.value()}/{self.folder_progress.pgb.maximum()}')

    def file_choose(self):
        filePath = QtWidgets.QFileDialog.getOpenFileName(self, "选择图片", "", "*.jpg;;*.png;;All Files(*)")[0]
        if filePath:
            self.statusBar.showMessage(f"当前选择的文件路径为: {filePath}")
            self.file_type = 'file'
            self.file_path = filePath
            img = cv2.imdecode(np.fromfile(self.file_path, dtype=np.uint8), -1)
            self.cur_img = img
            self.show_image(self.detect_show_label)

    def floder_choose(self):
        folderPath = QtWidgets.QFileDialog.getExistingDirectory(self,"选取文件夹","./")
        if folderPath:
            self.statusBar.showMessage(f"当前选择的文件夹路径为: {folderPath}")
            self.file_type = 'folder'
            self.file_path = folderPath
            all_num = len(DetThread.get_image_files(self.file_path))
            self.folder_progress = Progress_show()
            # 初始化进度条的范围
            self.folder_progress.pgb.setMinimum(0)
            self.folder_progress.pgb.setMaximum(all_num)
            self.folder_progress.pgb.setValue(0)
            # 设置进度条文字格式
            self.folder_progress.pgb.setFormat(f'已经检测 {self.folder_progress.pgb.value()}/{self.folder_progress.pgb.maximum()}')

    def on_max_btn_clicked(self):
        # 最大化与复原窗口
        desktop = QApplication.desktop()
        screen_number = desktop.screenNumber(QCursor.pos())
        screen_size = desktop.screenGeometry(screen_number)
        screen_width, screen_height = screen_size.width(), screen_size.height()
        self.max_restore(x=screen_width, y=screen_height)

    def max_restore(self, x, y):
        if self.maximized:  # 如果当前是最大化状态，则恢复窗口大小
            self.move(self.last_x, self.last_y)
            self.resize(self.nol_width, self.nol_height)
            self.maxButton.setIcon(QIcon(':/icon/res/彩色图标/fullscreen.png'))
        else:  # 否则，最大化窗口
            self.last_x, self.last_y = self.x(), self.y()  # 存下当前窗口位置
            self.move(0, 0)  # 移动窗口至屏幕左上角
            self.resize(x, y)  # 调整窗口大小到全屏
            self.maxButton.setIcon(QIcon(':/icon/res/彩色图标/还原2.png'))
        # 切换状态
        self.maximized = not self.maximized

    def resizeEvent(self, event):
        super().resizeEvent(event)
        if self.cur_img is not None:
            self.show_image(self.detect_show_label)

        # 窗口大小变化时重新调整背景大小
        pixmap = QPixmap(":/img/res/background.png")
        scaled_pixmap = pixmap.scaled(self.size(), Qt.KeepAspectRatioByExpanding)
        palette = QPalette()
        palette.setBrush(QPalette.Window, QBrush(scaled_pixmap))
        self.setPalette(palette)

    def on_resize(self, event):
        self.background = self.background.scaled(self.size(), Qt.IgnoreAspectRatio)
        self.update()

    def minimizeAction(self):
        # 最小化窗口
        self.setWindowState(Qt.WindowMinimized)

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.m_flag = True
            self.m_Position = event.globalPos() - self.pos()  # 获取鼠标相对窗口的位置
            event.accept()
            self.setCursor(QCursor(Qt.OpenHandCursor))  # 更改鼠标图标

    def mouseMoveEvent(self, QMouseEvent):
        if Qt.LeftButton and self.m_flag:
            self.move(QMouseEvent.globalPos() - self.m_Position)  # 更改窗口位置
            QMouseEvent.accept()

    def mouseReleaseEvent(self, QMouseEvent):
        self.m_flag = False
        self.setCursor(QCursor(Qt.ArrowCursor))

    def video_choose(self):
        videoPath = QtWidgets.QFileDialog.getOpenFileName(self, "选择视频", "", "*.mp4;;*.avi;;All Files(*)")[0]
        if videoPath:
            self.statusBar.showMessage(f"当前选择的视频路径为: {videoPath}")
            self.file_type = 'video'
            self.file_path = videoPath
            cap = cv2.VideoCapture(self.file_path)
            rval, frame = cap.read()
            raw_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
            raw_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
            fps = cap.get(cv2.CAP_PROP_FPS)  # 获取视频原帧率
            self.videoWriter = cv2.VideoWriter('out/result.mp4', cv2.VideoWriter_fourcc(*'mp4v'), fps,(raw_width, raw_height))
            self.cur_img = frame
            self.show_image(self.detect_show_label)
            cap.release()
    def camera_choose(self,camerapath):
        self.statusBar.showMessage(f"当前调用摄像头地址为：{camerapath}")
        self.file_type = 'camera'
        self.file_path = camerapath
        if len(camerapath) < 2:
            self.file_path = int(camerapath)
        cap = cv2.VideoCapture(self.file_path)
        rval, frame = cap.read()
        self.cur_img = frame
        self.show_image(self.detect_show_label)
        raw_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
        raw_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
        fps = cap.get(cv2.CAP_PROP_FPS)  # 获取视频原帧率
        self.videoWriter = cv2.VideoWriter('out/result.mp4', cv2.VideoWriter_fourcc(*'mp4v'), fps,(raw_width, raw_height))
        self.camerawin.close()
        cap.release()

    def result_output(self):
        # 打开结果输入的文件夹
        os.startfile(os.path.join(WORKPATH,'out'))

    def change_val(self, x, flag):
        if flag == 'confSpinBox':
            self.Slider_conf.setValue(int(x*100))
        elif flag == 'confSlider':
            self.SpinBox_conf.setValue(x/100)
        elif flag == 'iouSpinBox':
            self.Slider_iou.setValue(int(x*100))
        elif flag == 'iouSlider':
            self.SpinBox_iou.setValue(x/100)
        else:
            pass

if __name__ == '__main__':
    app = QApplication(sys.argv)
    log_win = Login()
    main_win = mainwin()
    log_win.loginsuccess.connect(lambda : main_win.show())
    log_win.show()
    sys.exit(app.exec_())